﻿using System;
using System.Collections.Generic;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
using System.Text;
using System.Threading.Tasks;
using RabbitMQ.Client;
using GrayParrot.Configuration;
using GrayParrot.RabbitMQ.Configuration;

namespace GrayParrot.RabbitMQ
{
    public class RabbitMQService
    {
        private IConnection m_connection = null;
        private Subscriptions m_subs = null;
        private IModel m_channel = null;

        public IModel Channel
        {
            get { return m_channel; }
            internal set { m_channel = value; }
        }

        public Endpoint GetSubscriptions()
        {
            Endpoint retValue = null;

            /* leggo la configurazione delle subscriptions da file di configurazione */
            ConfigurationManagerHelper pp = new ConfigurationManagerHelper();
            retValue = pp.GetDefaultEndpoint();
            m_subs = retValue.Subscriptions;

            return retValue;
        }

        public IConnection GetRabbitMQConnection(string hostName)
        {
            /* leggo la configurazione delle subscriptions da file di configurazione */
            Endpoint m_endpoint = GetSubscriptions();

            /* costuisco la connection factory */
            ConnectionFactory connectionFactory = new ConnectionFactory();
            connectionFactory.HostName = hostName;
            connectionFactory.UserName = m_endpoint.Username; 
            connectionFactory.Password = m_endpoint.Password;

            m_connection = connectionFactory.CreateConnection();

            m_channel = SetUpSubscriptions(hostName);

            return m_connection;
        }

        public IModel GetRabbitMQModel()
        {
            IModel retValue = null;

            if (m_connection != null)
            {
                if (m_channel != null)
                {
                    retValue = m_channel;
                }
                else
                {
                    retValue = m_connection.CreateModel();
                }
            }

            return retValue;
        }

        public void Close()
        {
            if (m_connection != null)
            {
                if (m_connection.IsOpen)
                {
                    m_connection.Close();
                }
            }
        }

        public IModel SetUpSubscriptions(string hostName)
        {
            IModel retValue = null;

            if (m_connection != null)
            {
                retValue = m_connection.CreateModel();

                /* leggo la configurazione delle subscriptions da file di configurazione */
                foreach (Subscription s in m_subs)
                {
                    Dictionary<String, Object> args = new Dictionary<String, Object>();
                    args.Add("x-message-ttl", 922337193601728);
                    args.Add("x-expires", 922337193601728);

                    /* devo creare prima la corrispondente DL... */
                    retValue.ExchangeDeclare(s.Exchange + "-DL", ExchangeType.Direct, true, false, null);
                    retValue.QueueDeclare(s.Name + "-DL", true, false, false, args);
                    retValue.QueueBind(s.Name + "-DL", s.Exchange + "-DL", "");

                    /**/
                    args.Add("x-dead-letter-exchange", s.Exchange + "-DL");

                    /* ... poi la coda, e quindi assegnare la dead letter...*/
                    retValue.ExchangeDeclare(s.Exchange, ExchangeType.Fanout, true, false, null);
                    retValue.QueueDeclare(s.Name, true, false, false, args);
                    retValue.QueueBind(s.Name, s.Exchange, "");
                }
                /* leggo la configurazione delle subscriptions da file di configurazione */
            }

            //
            return retValue;
        }
    }
}
